#include "CLink/Utils/StringUtils.h"
#include <algorithm>
#include <cctype>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <locale>
#include <codecvt>

namespace CLink
{
namespace Utils
{

// 构造函数和析构函数
StringUtils::StringUtils() : m_data(), m_lastPlaceholderPos(0) {}

StringUtils::StringUtils(const std::string &str)
    : m_data(str), m_lastPlaceholderPos(0) {}

StringUtils::StringUtils(const char *str)
    : m_data(str ? str : ""), m_lastPlaceholderPos(0) {}

StringUtils::StringUtils(const StringUtils &other)
    : m_data(other.m_data), m_lastPlaceholderPos(other.m_lastPlaceholderPos) {}

StringUtils::StringUtils(StringUtils &&other) noexcept
    : m_data(std::move(other.m_data)), m_lastPlaceholderPos(other.m_lastPlaceholderPos) {}

// 赋值操作符
StringUtils &StringUtils::operator=(const StringUtils &other)
{
    if (this != &other)
    {
        m_data = other.m_data;
        m_lastPlaceholderPos = other.m_lastPlaceholderPos;
    }
    return *this;
}

StringUtils &StringUtils::operator=(const std::string &str)
{
    m_data = str;
    m_lastPlaceholderPos = 0;
    return *this;
}

StringUtils &StringUtils::operator=(const char *str)
{
    m_data = str ? str : "";
    m_lastPlaceholderPos = 0;
    return *this;
}

StringUtils &StringUtils::operator=(StringUtils &&other) noexcept
{
    if (this != &other)
    {
        m_data = std::move(other.m_data);
        m_lastPlaceholderPos = other.m_lastPlaceholderPos;
    }
    return *this;
}

// 基础操作
int StringUtils::length() const
{
    return static_cast<int>(m_data.length());
}

bool StringUtils::isEmpty() const
{
    return m_data.empty();
}

bool StringUtils::isNull() const
{
    return false; // std::string never null
}

void StringUtils::clear()
{
    m_data.clear();
    m_lastPlaceholderPos = 0;
}

const std::string &StringUtils::toString() const
{
    return m_data;
}

const char *StringUtils::toCString() const
{
    return m_data.c_str();
}

std::string &StringUtils::data()
{
    return m_data;
}

const std::string &StringUtils::data() const
{
    return m_data;
}

// 查找和替换
int StringUtils::indexOf(const std::string &subStr, int from) const
{
    if (subStr.empty() || from < 0 || from >= static_cast<int>(m_data.size()))
    {
        return -1;
    }
    size_t pos = m_data.find(subStr, from);
    return pos == std::string::npos ? -1 : static_cast<int>(pos);
}

int StringUtils::lastIndexOf(const std::string &subStr, int from) const
{
    if (subStr.empty())
    {
        return -1;
    }
    size_t start = from < 0 ? std::string::npos : static_cast<size_t>(from);
    size_t pos = m_data.rfind(subStr, start);
    return pos == std::string::npos ? -1 : static_cast<int>(pos);
}

bool StringUtils::contains(const std::string &subStr) const
{
    return m_data.find(subStr) != std::string::npos;
}

bool StringUtils::startsWith(const std::string &subStr) const
{
    return m_data.rfind(subStr, 0) == 0;
}

bool StringUtils::endsWith(const std::string &subStr) const
{
    if (subStr.length() > m_data.length())
    {
        return false;
    }
    return m_data.compare(m_data.length() - subStr.length(), subStr.length(), subStr) == 0;
}

int StringUtils::count(const std::string &subStr) const
{
    if (subStr.empty())
    {
        return 0;
    }
    int count = 0;
    size_t pos = 0;
    while ((pos = m_data.find(subStr, pos)) != std::string::npos)
    {
        ++count;
        pos += subStr.length();
    }
    return count;
}

StringUtils &StringUtils::replace(const std::string &before, const std::string &after)
{
    size_t pos = 0;
    while ((pos = m_data.find(before, pos)) != std::string::npos)
    {
        m_data.replace(pos, before.length(), after);
        pos += after.length();
    }
    return *this;
}

StringUtils StringUtils::replaced(const std::string &before, const std::string &after) const
{
    StringUtils result(*this);
    result.replace(before, after);
    return result;
}

StringUtils &StringUtils::replace(int position, int n, const std::string &after)
{
    if (position < 0 || n < 0 || position + n > static_cast<int>(m_data.length()))
    {
        return *this;
    }
    m_data.replace(position, n, after);
    return *this;
}

StringUtils StringUtils::replaced(int position, int n, const std::string &after) const
{
    StringUtils result(*this);
    result.replace(position, n, after);
    return result;
}

// 正则表达式
bool StringUtils::matches(const std::string &pattern) const
{
    try
    {
        std::regex re(pattern);
        return std::regex_match(m_data, re);
    }
    catch (const std::regex_error &)
    {
        return false;
    }
}

StringUtils StringUtils::regexReplace(const std::string &pattern, const std::string &after) const
{
    try
    {
        std::regex re(pattern);
        return StringUtils(std::regex_replace(m_data, re, after));
    }
    catch (const std::regex_error &)
    {
        return *this;
    }
}

std::vector<StringUtils> StringUtils::regexMatches(const std::string &pattern) const
{
    std::vector<StringUtils> result;
    try
    {
        std::regex re(pattern);
        std::sregex_iterator it(m_data.begin(), m_data.end(), re);
        std::sregex_iterator end;
        for (; it != end; ++it)
        {
            result.emplace_back(it->str());
        }
    }
    catch (const std::regex_error &)
    {
        // 忽略错误
    }
    return result;
}

// 子字符串操作
StringUtils StringUtils::mid(int position, int n) const
{
    if (position < 0 || position >= static_cast<int>(m_data.length()))
    {
        return StringUtils();
    }
    if (n < 0 || position + n > static_cast<int>(m_data.length()))
    {
        n = static_cast<int>(m_data.length()) - position;
    }
    return StringUtils(m_data.substr(position, n));
}

StringUtils StringUtils::left(int n) const
{
    if (n <= 0)
    {
        return StringUtils();
    }
    if (n >= static_cast<int>(m_data.length()))
    {
        return *this;
    }
    return StringUtils(m_data.substr(0, n));
}

StringUtils StringUtils::right(int n) const
{
    if (n <= 0)
    {
        return StringUtils();
    }
    if (n >= static_cast<int>(m_data.length()))
    {
        return *this;
    }
    return StringUtils(m_data.substr(m_data.length() - n));
}

StringUtils StringUtils::section(const std::string &delim, int start, int end) const
{
    std::vector<StringUtils> parts = split(delim);
    if (start < 0)
    {
        start += static_cast<int>(parts.size());
    }
    if (end < 0)
    {
        end += static_cast<int>(parts.size());
    }
    if (start < 0 || start >= static_cast<int>(parts.size()) || end < start)
    {
        return StringUtils();
    }
    end = std::min(end, static_cast<int>(parts.size()) - 1);

    StringUtils result;
    for (int i = start; i <= end; ++i)
    {
        if (i > start)
        {
            result.append(delim);
        }
        result.append(parts[i]);
    }
    return result;
}

std::vector<StringUtils> StringUtils::split(const std::string &sep) const
{
    std::vector<StringUtils> result;
    if (sep.empty())
    {
        for (char c : m_data)
        {
            result.emplace_back(std::string(1, c));
        }
        return result;
    }

    size_t start = 0;
    size_t end = m_data.find(sep);
    while (end != std::string::npos)
    {
        result.emplace_back(m_data.substr(start, end - start));
        start = end + sep.length();
        end = m_data.find(sep, start);
    }
    result.emplace_back(m_data.substr(start));
    return result;
}

StringUtils StringUtils::join(const std::vector<StringUtils> &list, const std::string &sep)
{
    StringUtils result;
    for (size_t i = 0; i < list.size(); ++i)
    {
        if (i != 0)
        {
            result.append(sep);
        }
        result.append(list[i]);
    }
    return result;
}

// 大小写转换
StringUtils &StringUtils::toLower()
{
    std::transform(m_data.begin(), m_data.end(), m_data.begin(),
                    [](unsigned char c)
                    { return std::tolower(c); });
    return *this;
}

StringUtils &StringUtils::toUpper()
{
    std::transform(m_data.begin(), m_data.end(), m_data.begin(),
                    [](unsigned char c)
                    { return std::toupper(c); });
    return *this;
}

StringUtils StringUtils::toLower() const
{
    StringUtils result(*this);
    result.toLower();
    return result;
}

StringUtils StringUtils::toUpper() const
{
    StringUtils result(*this);
    result.toUpper();
    return result;
}

bool StringUtils::isLower() const
{
    return std::all_of(m_data.begin(), m_data.end(),
                        [](unsigned char c)
                        { return !std::isalpha(c) || std::islower(c); });
}

bool StringUtils::isUpper() const
{
    return std::all_of(m_data.begin(), m_data.end(),
                        [](unsigned char c)
                        { return !std::isalpha(c) || std::isupper(c); });
}

// 数字转换
StringUtils StringUtils::number(int n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(unsigned int n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(long n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(unsigned long n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(long long n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(unsigned long long n, int base)
{
    std::ostringstream oss;
    if (base == 10)
    {
        oss << n;
    }
    else
    {
        oss << std::setbase(base) << n;
    }
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(float n, char format, int precision)
{
    std::ostringstream oss;
    oss << std::setprecision(precision);
    switch (format)
    {
    case 'f':
        oss << std::fixed;
        break;
    case 'e':
        oss << std::scientific;
        break;
    case 'g':
        oss << std::defaultfloat;
        break;
    default:
        break;
    }
    oss << n;
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(double n, char format, int precision)
{
    std::ostringstream oss;
    oss << std::setprecision(precision);
    switch (format)
    {
    case 'f':
        oss << std::fixed;
        break;
    case 'e':
        oss << std::scientific;
        break;
    case 'g':
        oss << std::defaultfloat;
        break;
    default:
        break;
    }
    oss << n;
    return StringUtils(oss.str());
}

StringUtils StringUtils::number(long double n, char format, int precision)
{
    std::ostringstream oss;
    oss << std::setprecision(precision);
    switch (format)
    {
    case 'f':
        oss << std::fixed;
        break;
    case 'e':
        oss << std::scientific;
        break;
    case 'g':
        oss << std::defaultfloat;
        break;
    default:
        break;
    }
    oss << n;
    return StringUtils(oss.str());
}

// 字符串转换
int StringUtils::toInt(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        int result = std::stoi(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

long StringUtils::toLong(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        long result = std::stol(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

long long StringUtils::toLongLong(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        long long result = std::stoll(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

unsigned int StringUtils::toUInt(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        unsigned long result = std::stoul(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return static_cast<unsigned int>(result);
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

unsigned long StringUtils::toULong(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        unsigned long result = std::stoul(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

unsigned long long StringUtils::toULongLong(bool *ok, int base) const
{
    try
    {
        size_t pos = 0;
        unsigned long long result = std::stoull(m_data, &pos, base);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0;
    }
}

float StringUtils::toFloat(bool *ok) const
{
    try
    {
        size_t pos = 0;
        float result = std::stof(m_data, &pos);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0.0f;
    }
}

double StringUtils::toDouble(bool *ok) const
{
    try
    {
        size_t pos = 0;
        double result = std::stod(m_data, &pos);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0.0;
    }
}

long double StringUtils::toLongDouble(bool *ok) const
{
    try
    {
        size_t pos = 0;
        long double result = std::stold(m_data, &pos);
        if (ok)
            *ok = pos == m_data.length();
        return result;
    }
    catch (...)
    {
        if (ok)
            *ok = false;
        return 0.0L;
    }
}

// 字符串填充和修剪
StringUtils &StringUtils::prepend(const std::string &str)
{
    m_data.insert(0, str);
    return *this;
}

StringUtils &StringUtils::append(const std::string &str)
{
    m_data.append(str);
    return *this;
}

StringUtils &StringUtils::insert(int position, const std::string &str)
{
    if (position >= 0 && position <= static_cast<int>(m_data.length()))
    {
        m_data.insert(position, str);
    }
    return *this;
}

StringUtils &StringUtils::remove(int position, int n)
{
    if (position >= 0 && n >= 0 && position + n <= static_cast<int>(m_data.length()))
    {
        m_data.erase(position, n);
    }
    return *this;
}

StringUtils &StringUtils::truncate(int position)
{
    if (position >= 0 && position <= static_cast<int>(m_data.length()))
    {
        m_data.resize(position);
    }
    return *this;
}

StringUtils &StringUtils::chop(int n)
{
    if (n >= 0)
    {
        m_data.resize(m_data.length() - std::min(static_cast<size_t>(n), m_data.length()));
    }
    return *this;
}

StringUtils &StringUtils::fill(char ch, int size)
{
    if (size >= 0)
    {
        m_data.assign(size, ch);
    }
    return *this;
}

StringUtils &StringUtils::leftJustified(int width, char fill, bool truncate)
{
    if (static_cast<int>(m_data.length()) < width)
    {
        m_data.append(width - m_data.length(), fill);
    }
    else if (truncate && static_cast<int>(m_data.length()) > width)
    {
        m_data.resize(width);
    }
    return *this;
}

StringUtils &StringUtils::rightJustified(int width, char fill, bool truncate)
{
    if (static_cast<int>(m_data.length()) < width)
    {
        m_data.insert(0, width - m_data.length(), fill);
    }
    else if (truncate && static_cast<int>(m_data.length()) > width)
    {
        m_data = m_data.substr(m_data.length() - width);
    }
    return *this;
}

StringUtils &StringUtils::trimmed()
{
    auto notSpace = [](int ch)
    { return !std::isspace(ch); };
    m_data.erase(m_data.begin(), std::find_if(m_data.begin(), m_data.end(), notSpace));
    m_data.erase(std::find_if(m_data.rbegin(), m_data.rend(), notSpace).base(), m_data.end());
    return *this;
}

StringUtils &StringUtils::simplified()
{
    trimmed();
    auto newEnd = std::unique(m_data.begin(), m_data.end(), [](char a, char b)
                                { return std::isspace(a) && std::isspace(b); });
    m_data.erase(newEnd, m_data.end());
    return *this;
}

void StringUtils::replaceNextPlaceholder(const std::string &replacement)
{
    size_t pos = m_data.find("%", m_lastPlaceholderPos);
    if (pos != std::string::npos && pos + 1 < m_data.length() && isdigit(m_data[pos + 1]))
    {
        m_data.replace(pos, 2, replacement);
        m_lastPlaceholderPos = pos + replacement.length();
    }
}

bool StringUtils::isSpace(char c)
{
    return std::isspace(static_cast<unsigned char>(c));
}

} // namespace Utils
}